<?php

namespace App\Imports;

use Illuminate\Support\Facades\Hash;
// use Maatwebsite\Excel\Concerns\ToModel;
use Maatwebsite\Excel\Concerns\ToCollection;
use Illuminate\Support\Collection;
use App\Models\Admin\User;
use App\Models\Admin\RelationBackup;
use DB, Auth;

class UserImport implements ToCollection
{
    // 根用户实例，层级为0
    protected $rootUser;

    // 根用户手机号
    protected $rootUserPhone = 1;

    // 导入用户店铺ID
    protected $storeId = 3;
    
    // 存储已导入的用户（按手机号索引）
    protected $importedUsers = [];

    // 已注册的手机号
    protected $existingPhones;
    
    // 是否使用优先级排序
    protected $usePriority;
    
    // 成功导入的用户计数
    protected $successCount = 0;
    
    // 跳过导入的用户计数（用户已存在）
    protected $skippedCount = 0;
    
    // 导入失败的用户计数
    protected $failedCount = 0;
    
    // 存储导入失败的行信息
    protected $failedRows = [];
    
    /**
     * 构造函数
     * 
     * @param bool $usePriority 是否使用优先级排序（默认true）
     */
    // 根用户手机号可为空
    public function __construct(bool $usePriority = true)
    {
        $this->usePriority = $usePriority;
        
        // 预加载所有已存在的手机号
        $this->existingPhones = User::pluck('phone')->filter()->toArray();

        // 获取根用户（层级为0）
        $this->rootUser = User::where('id', '1')->first();   
    }

    public function collection(Collection $rows)
    {
        // 按推荐人分组并排序
        $grouped = $this->groupAndSort($rows);
        
        // 按推荐人层级处理
        $this->processByLevel($grouped);
    }

    /**
     * 按推荐人分组并排序
     * 
     * @param Collection $rows Excel行数据
     * @return array 分组后的用户数据
     */
    protected function groupAndSort($rows)
    {
        $grouped = [];
        
        foreach ($rows as $index => $row) {
            if($index==0){
                continue;
            }

            // +++ 新增：检测空行 +++
            $isEmptyRow = true;
            foreach ($row as $cell) {
                if ($cell !== null && trim($cell) !== '') {
                    $isEmptyRow = false;
                    break;
                }
            }
            if ($isEmptyRow) {
                continue; // 跳过空行
            }
            // --- 新增结束 ---

            $phone = $row['0'] ?? null;
            $password = $row['1'] ?? null;
            $recommenderPhone = $row['2'] ?? null;
            $priority = $this->usePriority ? ($row['3'] ?? 999) : 999;
            
            if (!$phone || !$password) {
                $this->failedCount++;
                $this->failedRows[] = [
                    'row' => $index + 1,
                    'phone' => $phone,
                    'recommender_phone' => $recommenderPhone,
                    'error' => '手机号或密码为空'
                ];
                continue;
            }
            
            // 检查手机号唯一性
            if (in_array($phone, $this->existingPhones)) {
                throw new \Exception($phone."手机号已存在");
            }

            // 一级用户推荐人设为根用户
            if (!$recommenderPhone) {
                $recommenderPhone = $this->rootUserPhone;
            }
            
            if (!isset($grouped[$recommenderPhone])) {
                $grouped[$recommenderPhone] = [];
            }
            
            $grouped[$recommenderPhone][] = [
                'phone' => $phone,
                'password' => $password,
                'priority' => (int)$priority, // 确保优先级为整数
                'row_index' => $index + 1 // 记录行号用于错误报告
            ];
        }
        
        // 对每个推荐人组内的用户按优先级排序
        foreach ($grouped as &$group) {
            usort($group, function($a, $b) {
                // 如果优先级相同，保持原有顺序
                if ($a['priority'] === $b['priority']) {
                    return 0;
                }
                // 优先级低的排在前面（数字越小优先级越高）
                return $a['priority'] <=> $b['priority'];
            });
        }
        
        return $grouped;
    }
    /**
     * 按层级处理用户导入（使用BFS广度优先算法）
     * 
     * @param array $grouped 分组后的用户数据
     */
    protected function processByLevel($grouped)
    {
        // 初始化队列：从根用户开始
        $queue = [$this->rootUserPhone => $grouped[$this->rootUserPhone] ?? []];
        unset($grouped[$this->rootUserPhone]);// 从分组中移除根用户组
        
         // BFS处理队列
        while (!empty($queue)) {
            // 获取当前推荐人及其待导入用户
            $currentRecommender = array_key_first($queue);
            $usersToImport = $queue[$currentRecommender];
            unset($queue[$currentRecommender]);
            
            // 处理当前推荐人的所有用户
            foreach ($usersToImport as $userData) {
                try {
                    // 创建用户并添加到嵌套集合
                    $this->createUser($userData, $currentRecommender);
                    $this->successCount++;
                } catch (\Exception $e) {
                    // 记录导入失败的信息
                    $this->failedCount++;
                    $this->failedRows[] = [
                        'row' => $userData['row_index'],
                        'phone' => $userData['phone'],
                        'recommender_phone' => $currentRecommender,
                        'error' => $e->getMessage()
                    ];
                }
                
                // 如果新用户是其他人的推荐人，添加到队列
                $newUserPhone = $userData['phone'];
                if (isset($grouped[$newUserPhone])) {
                    $queue[$newUserPhone] = $grouped[$newUserPhone];
                    unset($grouped[$newUserPhone]);// 从分组中移除已处理的分组
                }
            }
        }
        
        // 处理孤立用户（推荐人不在队列中的用户）
        foreach ($grouped as $recommenderPhone => $users) {
            foreach ($users as $userData) {
                try {
                    $this->createUser($userData, $recommenderPhone);
                    $this->successCount++;
                } catch (\Exception $e) {
                    $this->failedCount++;
                    $this->failedRows[] = [
                        'row' => $userData['row_index'],
                        'phone' => $userData['phone'],
                        'recommender_phone' => $recommenderPhone,
                        'error' => $e->getMessage()
                    ];
                }
            }
        }
    }

    /**
     * 创建用户并添加到嵌套集合
     * 
     * @param array $data 用户数据
     * @param string $recommenderPhone 推荐人手机号
     * @throws \Exception 如果推荐人不存在
     */
    protected function createUser($data, $recommenderPhone)
    {
        // 检查用户是否已存在
        if (User::where('phone', $data['phone'])->exists()) {
            $this->skippedCount++;
            return;
        }
        
        // 查找推荐人
        $recommender = $this->findRecommender($recommenderPhone);
        
        if (!$recommender) {
            throw new \Exception("推荐人 {$recommenderPhone} 未找到");
        }
        
        DB::transaction(function () use ($data, $recommender) {
            // 1. 先创建节点但不设置左右值
            $user = User::create([
                'phone' => $data['phone'],
                'password' => Hash::make($data['password']),
                'level' => $recommender->level + 1,
                'pid' => $recommender->id,
                'store_id' => $this->storeId,
                'open_id' => (string)$data['phone'],
                'is_regist' => 1,
                'regist_at' => date('Y-m-d H:i:s'),
                'left' => 0, // 临时值
                'right' => 0 // 临时值
            ]);
            
            // 2. 锁定父节点
            $recommender = User::where('id', $recommender->id)
                ->lockForUpdate()
                ->first();
                
            $parentRight = $recommender->right;

            User::where('right', '>=', $parentRight)->lockForUpdate()->get();
            // 3. 更新嵌套集合
            DB::update("
                UPDATE users 
                SET `left` = IF(`left` > ?, `left` + 2, `left`),
                    `right` = IF(`right` >= ?, `right` + 2, `right`)
                WHERE `right` >= ?
            ", [$parentRight, $parentRight, $parentRight]);
            
            // 4. 设置新节点的左右值
            $user->left = $recommender->right;
            $user->right = $recommender->right + 1;
            $user->save();

            // 5. 更新父节点右值
            $recommender->right = $recommender->right + 2;
            $recommender->save();
            
            // +++ 新增：插入关系备份表数据 +++
            $pid = $recommender->id == 1 ? 1 : $recommender->id; // 直接上级ID
            $parentAll = $this->getParentAllPath($recommender); // 获取所有上级路径
            
            RelationBackup::create([
                'user_id' => $user->id,
                'pid' => $pid,
                'parent_all' => $parentAll,
                'level' => $user->level, // 代数（层级）
                'type' => 4, // 后台导入用户类型
            ]);
            // --- 新增结束 ---

            // 将新用户添加到已导入用户映射中
            $this->importedUsers[$data['phone']] = $user;
        });
    }

    /**
     * 获取用户的所有上级路径
     * 
     * @param User $recommender 推荐人实例
     * @return string 所有上级ID路径
     */
    protected function getParentAllPath(User $recommender): string
    {
        // 根用户直接返回'1'
        if ($recommender->id == 1) {
            return '1';
        }
        
        // 查询推荐人的关系备份记录
        $recommenderBackup = DB::table('relation_backups')
            ->where('user_id', $recommender->id)
            ->first();
        
        if (!$recommenderBackup) {
            throw new \Exception("推荐人关系备份记录不存在: {$recommender->id}");
        }
        
        // 拼接路径: 推荐人的路径 + 推荐人ID
        return $recommenderBackup->parent_all . '-' . $recommender->id;
    }
    
    /**
     * 查找推荐人
     * 
     * @param string $phone 推荐人手机号
     * @return User|null 推荐人用户实例或null
     */
    protected function findRecommender($phone)
    {
        // 1. 检查是否是根用户
        if ($phone === $this->rootUserPhone) {
            return $this->rootUser;
        }
        
        // 2. 检查是否已导入
        if (isset($this->importedUsers[$phone])) {
            return $this->importedUsers[$phone];
        }
        
        // 3. 从数据库中查找已存在的用户
        return User::where('phone', $phone)->first();
    }

    /**
     * 获取成功导入用户数
     * 
     * @return int
     */
    public function getSuccessCount(): int
    {
        return $this->successCount;
    }

    /**
     * 获取跳过导入用户数（已存在用户）
     * 
     * @return int
     */
    public function getSkippedCount(): int
    {
        return $this->skippedCount;
    }

    /**
     * 获取导入失败用户数
     * 
     * @return int
     */
    public function getFailedCount(): int
    {
        return $this->failedCount;
    }
    
    /**
     * 获取导入失败的行详情
     * 
     * @return array
     */
    public function getFailedRows(): array
    {
        return $this->failedRows;
    }
    
    /**
     * 获取根用户实例
     * 
     * @return User
     */
    public function getRootUser(): User
    {
        return $this->rootUser;
    }
}